Skip to content

[FEATURE] Support multiple LLM connectos with proper rate limit#285

Open
fen-qin wants to merge 6 commits into
opensearch-project:mainfrom
fen-qin:multiple_llm
Open

[FEATURE] Support multiple LLM connectos with proper rate limit#285
fen-qin wants to merge 6 commits into
opensearch-project:mainfrom
fen-qin:multiple_llm

Conversation

@fen-qin
Copy link
Copy Markdown
Collaborator

@fen-qin fen-qin commented Oct 29, 2025

Description

This PR introduces comprehensive multi-provider LLM support to the OpenSearch Search Relevance plugin, enabling users to work with OpenAI, Claude, Cohere, and DeepSeek models through a unified interface. Additionally, it implements adaptive rate limiting to prevent API throttling and improve system reliability.

Core Features

1. Multi-Provider LLM Connector Framework

Transitioned from OpenAI-only to a flexible connector pattern supporting multiple LLM providers.

Key Components:

  • LLMConnector interface with standardized methods for prompt formatting and response extraction
  • LLMConnectorFactory for creating provider-specific connectors
  • ConnectorType enum supporting OPENAI, CLAUDE, COHERE, and DEEPSEEK
/**
 * Enum representing different LLM connector types
 */
public enum ConnectorType {
    OPENAI("openai"),
    CLAUDE("claude"),
    COHERE("cohere"),
    DEEPSEEK("deepseek");

2. REST API Integration

Added optional connectorType and rateLimit parameter to LLM judgment requests.

API Usage:

{
  "type": "LLM_JUDGMENT",
  "modelId": "anthropic.claude-3-5-haiku",
  "connectorType": "claude",
  "rateLimit": 1000,
  "querySetId": "test-queries"
}

3. Adaptive Rate Limiting System

Prevents API rate limit errors through adaptive learning and circuit breaking.

Key Features:
Per-Model State: Separate rate limiting for each model/connector combination
Adaptive Learning: Automatically adjusts delays based on success/failure patterns
Circuit Breaker: Temporarily stops requests after consecutive failures (threshold: 10)
Conservative Recovery: Gradual rate reduction (0.9x) after sustained success
Resource Management: Proper thread pool lifecycle with cleanup

Rate Limiting Logic:

  • Initial rate limit from user configuration
  • Exponential backoff (2x) on rate limit errors
  • Circuit breaker activation after 10 consecutive failures
  • Automatic cleanup of stale entries after 1 hour

E2E Testing

  • create remote connector following the instructions under /docs/llm-model, validated for 4 ConnectorType: OpenAI, Claude, DeepSeek and Cohere
  • sample CLAUDE judgment
PUT _plugins/_search_relevance/judgments
{
  "name": "claude_relevant_final_20241125",
  "type": "LLM_JUDGMENT",
  "querySetId": "d4f2e581-4fab-48cb-9d87-10a76f27932b",
  "searchConfigurationList": ["b7265415-b225-4769-bde3-fa78ddecae69"],
  "size": 5,
  "modelId": "YMj3vJoB0FcmkmOuPONM",
  "rateLimit": "3000",
  "connectorType": "CLAUDE",
  "ignoreFailure": false,
  "overwriteCache": true
}
  • sample response
{
  "_index": "search-relevance-judgment",
  "_id": "b4f5cb24-3554-4182-8671-7d6998208ae2",
  "_version": 2,
  "_seq_no": 21,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "id": "b4f5cb24-3554-4182-8671-7d6998208ae2",
    "timestamp": "2025-11-25T22:15:37.375Z",
    "name": "claude_relevant_final_20241125",
    "status": "COMPLETED",
    "type": "LLM_JUDGMENT",
    "metadata": {
      "contextFields": [],
      "ignoreFailure": false,
      "connectorType": "CLAUDE",
      "llmJudgmentRatingType": "SCORE0_1",
      "rateLimit": 3000,
      "size": 5,
      "modelId": "YMj3vJoB0FcmkmOuPONM",
      "overwriteCache": true,
      "searchConfigurationList": [
        "b7265415-b225-4769-bde3-fa78ddecae69"
      ],
      "tokenLimit": 5000,
      "promptTemplate": "Rate the relevance of the search results to the query. SearchText: {{searchText}}; Results: {{hits}}",
      "querySetId": "d4f2e581-4fab-48cb-9d87-10a76f27932b"
    },
    "judgmentRatings": [
      {
        "query": "DNA methylation in human cells",
        "ratings": [
          {
            "docId": "39801095",
            "rating": "0.8"
          },
          {
            "docId": "7808055",
            "rating": "0.8"
          },
          {
            "docId": "4679264",
            "rating": "0.7"
          },
          {
            "docId": "9291668",
            "rating": "0.9"
          },
          {
            "docId": "13955536",
            "rating": "0.5"
          }
        ]
      },
      {
        "query": "myelin basic protein gene expression",
        "ratings": [
          {
            "docId": "3788528",
            "rating": "0.9"
          },
          {
            "docId": "19238",
            "rating": "1.0"
          },
          {
            "docId": "18447487",
            "rating": "0.1"
          },
          {
            "docId": "35467590",
            "rating": "0.9"
          },
          {
            "docId": "20363389",
            "rating": "0.1"
          }
        ]
      },
      {
        "query": "myelodysplasia induction mechanisms",
        "ratings": [
          {
            "docId": "8385277",
            "rating": "0.7"
          },
          {
            "docId": "34935825",
            "rating": "0.1"
          },
          {
            "docId": "42421723",
            "rating": "0.1"
          },
          {
            "docId": "1617327",
            "rating": "0.8"
          },
          {
            "docId": "5836",
            "rating": "0.9"
          }
        ]
      },
      {
        "query": "cerebral white matter development",
        "ratings": [
          {
            "docId": "22107641",
            "rating": "0.4"
          },
          {
            "docId": "1472815",
            "rating": "0.3"
          },
          {
            "docId": "4983",
            "rating": "1.0"
          },
          {
            "docId": "1412089",
            "rating": "0.3"
          },
          {
            "docId": "7224632",
            "rating": "0.4"
          }
        ]
      },
      {
        "query": "peripheral blood mononuclear cells",
        "ratings": [
          {
            "docId": "17463549",
            "rating": "0.4"
          },
          {
            "docId": "18670",
            "rating": "1.0"
          },
          {
            "docId": "45449835",
            "rating": "0.7"
          },
          {
            "docId": "10786948",
            "rating": "0.7"
          },
          {
            "docId": "38712515",
            "rating": "0.9"
          }
        ]
      },
      {
        "query": "transcription unit gene expression",
        "ratings": [
          {
            "docId": "9724974",
            "rating": "0.8"
          },
          {
            "docId": "19238",
            "rating": "0.7"
          },
          {
            "docId": "33986507",
            "rating": "0.9"
          },
          {
            "docId": "28390999",
            "rating": "0.5"
          },
          {
            "docId": "20179918",
            "rating": "0.6"
          }
        ]
      },
      {
        "query": "reverse transcription RNA",
        "ratings": [
          {
            "docId": "25175223",
            "rating": "0.7"
          },
          {
            "docId": "7912",
            "rating": "0.9"
          },
          {
            "docId": "39389082",
            "rating": "0.8"
          },
          {
            "docId": "14050257",
            "rating": "0.3"
          },
          {
            "docId": "43602749",
            "rating": "0.4"
          }
        ]
      },
      {
        "query": "immune system gene expression",
        "ratings": [
          {
            "docId": "5519177",
            "rating": "0.9"
          },
          {
            "docId": "19238",
            "rating": "0.8"
          },
          {
            "docId": "8604837",
            "rating": "0.4"
          },
          {
            "docId": "41120293",
            "rating": "0.5"
          },
          {
            "docId": "9784254",
            "rating": "0.7"
          }
        ]
      },
      {
        "query": "central nervous system development",
        "ratings": [
          {
            "docId": "14893428",
            "rating": "0.8"
          },
          {
            "docId": "12742164",
            "rating": "0.9"
          },
          {
            "docId": "22647695",
            "rating": "0.7"
          },
          {
            "docId": "43990286",
            "rating": "0.8"
          },
          {
            "docId": "6325527",
            "rating": "0.7"
          }
        ]
      },
      {
        "query": "human gene amplification",
        "ratings": [
          {
            "docId": "3210545",
            "rating": "0.8"
          },
          {
            "docId": "13759726",
            "rating": "0.5"
          },
          {
            "docId": "14315749",
            "rating": "0.4"
          },
          {
            "docId": "7912",
            "rating": "0.5"
          },
          {
            "docId": "4321947",
            "rating": "0.6"
          }
        ]
      },
      {
        "query": "protein synthesis regulation",
        "ratings": [
          {
            "docId": "29851836",
            "rating": "0.3"
          },
          {
            "docId": "12881593",
            "rating": "0.4"
          },
          {
            "docId": "4362729",
            "rating": "0.7"
          },
          {
            "docId": "6820680",
            "rating": "0.4"
          },
          {
            "docId": "15590539",
            "rating": "0.9"
          }
        ]
      },
      {
        "query": "cell differentiation pathways",
        "ratings": [
          {
            "docId": "5508750",
            "rating": "0.7"
          },
          {
            "docId": "25251625",
            "rating": "0.4"
          },
          {
            "docId": "9460704",
            "rating": "0.6"
          },
          {
            "docId": "13116880",
            "rating": "0.8"
          },
          {
            "docId": "13798951",
            "rating": "0.7"
          }
        ]
      },
      {
        "query": "molecular biology mechanisms",
        "ratings": [
          {
            "docId": "25504006",
            "rating": "0.8"
          },
          {
            "docId": "6673421",
            "rating": "0.5"
          },
          {
            "docId": "84580585",
            "rating": "0.7"
          },
          {
            "docId": "30919024",
            "rating": "0.7"
          },
          {
            "docId": "8856690",
            "rating": "0.5"
          }
        ]
      },
      {
        "query": "genetic transcription factors",
        "ratings": [
          {
            "docId": "11011905",
            "rating": "0.8"
          },
          {
            "docId": "28937856",
            "rating": "0.9"
          },
          {
            "docId": "4324278",
            "rating": "0.7"
          },
          {
            "docId": "4405194",
            "rating": "0.8"
          },
          {
            "docId": "3672261",
            "rating": "0.5"
          }
        ]
      },
      {
        "query": "cellular metabolism processes",
        "ratings": [
          {
            "docId": "12643937",
            "rating": "0.4"
          },
          {
            "docId": "24387017",
            "rating": "0.5"
          },
          {
            "docId": "33030946",
            "rating": "0.6"
          },
          {
            "docId": "9451684",
            "rating": "0.6"
          },
          {
            "docId": "27134527",
            "rating": "0.7"
          }
        ]
      },
      {
        "query": "enzyme activity regulation",
        "ratings": [
          {
            "docId": "12785130",
            "rating": "0.7"
          },
          {
            "docId": "18038955",
            "rating": "0.4"
          },
          {
            "docId": "29467201",
            "rating": "0.5"
          },
          {
            "docId": "13245542",
            "rating": "0.4"
          },
          {
            "docId": "22036571",
            "rating": "0.8"
          }
        ]
      },
      {
        "query": "signal transduction pathways",
        "ratings": [
          {
            "docId": "8210189",
            "rating": "0.7"
          },
          {
            "docId": "11083121",
            "rating": "0.7"
          },
          {
            "docId": "6363093",
            "rating": "0.8"
          },
          {
            "docId": "35395662",
            "rating": "0.8"
          },
          {
            "docId": "1225513",
            "rating": "0.9"
          }
        ]
      },
      {
        "query": "membrane protein function",
        "ratings": [
          {
            "docId": "6788835",
            "rating": "0.8"
          },
          {
            "docId": "27438378",
            "rating": "0.6"
          },
          {
            "docId": "38300781",
            "rating": "0.9"
          },
          {
            "docId": "37643601",
            "rating": "0.7"
          },
          {
            "docId": "34905328",
            "rating": "0.7"
          }
        ]
      },
      {
        "query": "chromosome structure organization",
        "ratings": [
          {
            "docId": "16562534",
            "rating": "0.3"
          },
          {
            "docId": "20045514",
            "rating": "0.7"
          },
          {
            "docId": "15669393",
            "rating": "0.1"
          },
          {
            "docId": "11141995",
            "rating": "0.9"
          },
          {
            "docId": "7468449",
            "rating": "0.8"
          }
        ]
      },
      {
        "query": "molecular genetics research",
        "ratings": [
          {
            "docId": "8126244",
            "rating": "0.7"
          },
          {
            "docId": "84580585",
            "rating": "0.7"
          },
          {
            "docId": "11913139",
            "rating": "0.6"
          },
          {
            "docId": "9196472",
            "rating": "0.9"
          },
          {
            "docId": "9872468",
            "rating": "0.8"
          }
        ]
      }
    ]
  }
}

Issues Resolved

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@fen-qin fen-qin force-pushed the multiple_llm branch 2 times, most recently from e198c3c to 099c74b Compare October 29, 2025 22:58
@fen-qin fen-qin marked this pull request as ready for review October 29, 2025 23:10
@fen-qin fen-qin changed the title support multiple LLM connectos with proper rate limit [FEATURE] Support multiple LLM connectos with proper rate limit Oct 29, 2025
Copy link
Copy Markdown
Member

@martin-gaievski martin-gaievski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good addition to the system, thanks for this contribution.

Few high level comments on top of what I posted in the code:

  • can we create a single class for LLM params, e.g LLMConfiguration, where we keep things like rateLimit, maxRetries, retryBackoff, maxTokens etc. Currently we do have all those params spread all over the code in different places. Separate class should help to keep logical structure and decouple logic from parameters.
  • we need to collect metric on retries, I think good way to do it is to use stats API that is part of the SRW repo. Check this PR where it has been introduced #63. We can collect number of retry attempts and delay
  • In future we need to think of a separate pool for retries. With current implementation system uses CompletableFuture.delayedExecutor which is basically common ForkJoinPool. Under high load with many retries this could exhaust the thread pool. This may be too much for this PR, more like a follow up change

ignoreFailure
);
List<String> unprocessedDocIds = docIds;
// List<String> unprocessedDocIds = deduplicateFromCache(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not needed in the final version

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. sure. this should be removed


private boolean isRetryableError(Exception e) {
String message = e.getMessage();
if (message == null) return true;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why it's retryable if without message? also please fix style, use curly braces

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class BedrockRateLimiter {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not everyone will use Bedrock as a platform. We need RateLimiter interface and BedrockRateLimiter will be one possible implementation of it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the high-level suggestions + this thread.

Yes, we should put a more general class MLConfiguration that can probably hold all common functions:

  • rateLimit, maxRetries, retryBackoff, maxTokens etc
  • prompt formatter
  • response processor

to make it more clear if anyone what to add a new model with customized input/output interface and setting.

ActionListener<String> listener
) {
// Apply rate limiting per chunk to handle multiple chunks per query
BedrockRateLimiter.applyRateLimit(connectorType, customRateLimit);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to create exact implementation of RateLimiter interface using some sort of a Factory, or factory method, probably makes sense to have it as class variable. Then call only interface methods.

this.rateLimit = rateLimitObj != null ? rateLimitObj : 0L;
}

public String getQuerySetId() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for bunch of getters you can use lombok getter

}
}

lastRequestTimes.put(key, System.currentTimeMillis());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map can grow indefinitely, I cannot see where we delete from it

long sleepTime = delayMs - timeSinceLastRequest;
try {
log.debug("Rate limiting {}: sleeping for {} ms", modelType, sleepTime);
Thread.sleep(sleepTime);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not inefficient to block threads with sleep. You can do multiple options, for example:

  1. Use ScheduledExecutorService, each time you need to sleep the thread, you do
    scheduler.schedule(() -> { future.complete(null); }, waitTime, TimeUnit.MILLISECONDS)

or even simpler approach - CompletableFuture with delay
CompletableFuture.delayedExecutor(delayMs, TimeUnit.MILLISECONDS) .execute(() -> {});

@fen-qin
Copy link
Copy Markdown
Collaborator Author

fen-qin commented Oct 30, 2025

Thanks @martin-gaievski for the review.
Adding @chloewqg @heemin32 to the thread.

This PR is about to do code refactoring on existing LLM processor, to make it supports models in a more general way:

  • aws bedrock models: claude, cohere, deepseek, openai
  • http endpoint models: openai, deepseek

and the interface should be extendable to onboard any other models

@chloewqg
Copy link
Copy Markdown
Contributor

Thanks @martin-gaievski for the review. Adding @chloewqg @heemin32 to the thread.

This PR is about to do code refactoring on existing LLM processor, to make it supports models in a more general way:

  • aws bedrock models: claude, cohere, deepseek, openai
  • http endpoint models: openai, deepseek

and the interface should be extendable to onboard any other models

Thanks for cc me. It does look like to be a lot of code conflicts with PR #264 We should think about how to merge it and the efforts to merge and resolve conflicts without having functionality break.

@chloewqg
Copy link
Copy Markdown
Contributor

Thanks @martin-gaievski for the review. Adding @chloewqg @heemin32 to the thread.
This PR is about to do code refactoring on existing LLM processor, to make it supports models in a more general way:

  • aws bedrock models: claude, cohere, deepseek, openai
  • http endpoint models: openai, deepseek

and the interface should be extendable to onboard any other models

Thanks for cc me. It does look like to be a lot of code conflicts with PR #264 We should think about how to merge it and the efforts to merge and resolve conflicts without having functionality break.

From the code comparison of Overlap between two PRs, it is not trivial work to merge and ensure not functionality breaks.

Signed-off-by: Fen Qin <mfenqin@amazon.com>
Signed-off-by: Fen Qin <mfenqin@amazon.com>
Signed-off-by: Fen Qin <mfenqin@amazon.com>
Signed-off-by: Fen Qin <mfenqin@amazon.com>
Signed-off-by: Fen Qin <mfenqin@amazon.com>
Signed-off-by: Fen Qin <mfenqin@amazon.com>
Copy link
Copy Markdown
Member

@martin-gaievski martin-gaievski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very good contribution, thank you for taking care of details and designing with a good level of abstractions. Overall code looks good to time, please address few minor comments and I'll approve PR.

/**
* Interface for LLM connector implementations that handle different LLM providers
*/
public interface LLMConnector {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is really good abstraction, thank you for allocating time and addressing this

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about adding one more method here, supportsJsonMode()? Claude/Cohere don't support json response natively, so by chance you may receive response that should be parsed differently

/**
* Adaptive rate limiter that learns optimal rates per model and handles circuit breaking
*/
public class AdaptiveRateLimiter {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please add abstraction layer and extract interface for rate limiter, similar to what you have done for LLMConnector. I suggest humble interface name RateLimiter

return CompletableFuture.failedFuture(new RuntimeException("Model appears to be unavailable: " + modelId));
}

long delayMs = state.calculateDelay();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need a metric for retry event, something like llm_rate_limit_retries with existing stat API, it's a counter that incremented on every retry.

Copy link
Copy Markdown
Collaborator

@heemin32 heemin32 Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the metric, I would like to know the final usage of it. How the metrics would help the user or administrator and can we achieve the same without using metrics?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The metrics recommendation was for observability completeness, it's not essential for this PR. The rate limiter already:

  • logs all throttling events (searchable in log aggregators)
  • reports job success/failure counts in the response
  • has a circuit breaker that stops requests on persistent failures

with such metric it's possible to build a monitoring system on a provider side, who may not have access to user data, but can detect spikes in retries. Later it should simplify troubleshooting for cases when lots of ratings are 0 because we retry and then failed, or experiment is running for a very long time (it's quite possible for some cloud providers that are giving low quotas that can lead to tens of minutes even on a simple experiment)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using stats, can we store it as part of experiment result?
When rating is 0, we should mark it as failure with its root cause. For experiment running for long, cx should be able to query the experiment and check its current status if we store all those data somewhere along with experiment metadata.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean process of generating ratings instead of experiment?

Users are able to use LLM for generating ratings in standalone mode, without any experiments. For example, my humble typical use case for SRW is - import query terms from external system, generate judgment ratings with LLM, run experiment. If I already have ratings I will not generate them again at all.

boolean overwriteCache = Optional.ofNullable((Boolean) source.get(OVERWRITE_CACHE)).orElse(Boolean.FALSE);

// Parse connectorType - optional, defaults to OpenAI
ConnectorType connectorType = ConnectorType.OPENAI; // default
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be null. It cannot have default as OPENAI until we also load a OPENAI modelId if no other connector is provided.

PutJudgmentRequest createRequest;
switch (type) {
case LLM_JUDGMENT -> {
String modelId = (String) source.get(MODEL_ID);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is high time we should break this into smaller methods. For that matter we can create a class out of it of what all is going in under LLM judgement.

Class name can be LlmjudgementType and UbiJudgementType

log.debug("DEBUG: predictSingleChunk called with modelId: {}", modelId);
RemoteInferenceInputDataSet dataset = (RemoteInferenceInputDataSet) mlInput.getInputDataset();
Map<String, String> params = dataset.getParameters();
public void predictSingleChunk(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add javadoc to all public methods and clearly articulate the purpose of them.

@@ -105,58 +111,76 @@
private void generateJudgmentRatingInternal(Map<String, Object> metadata, ActionListener<List<Map<String, Object>>> listener) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, we have excessive logging in this class. Almost at each small piece of code execution. We should reduce this.

boolean overwriteCache
) {
private Map<String, Object> processQueryTextAsync(LlmJudgmentContext context, String queryTextWithCustomInput) {
log.info("Processing query text judgment: {}", queryTextWithCustomInput);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am assuming if we have 1000 query terms then for each query term this line will be executed.

Processing query text judgment: {}" x 1000 times

return docIds;
}
List<String> processedDocIds = Collections.synchronizedList(new ArrayList<>());
AtomicBoolean hasFailure = new AtomicBoolean(false);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this hasFailure variable is used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants